package com.coursebooking.service;

import com.coursebooking.model.Booking;
import com.coursebooking.model.Course;
import com.coursebooking.model.Student;
import com.coursebooking.repository.BookingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
public class BookingService {

    @Autowired
    private BookingRepository bookingRepository;

    @Autowired
    private StudentService studentService;

    @Autowired
    private CourseService courseService;

    public Booking createBooking(Long studentId, Long courseId) {
        Optional<Student> studentOpt = studentService.findById(studentId);
        if (!studentOpt.isPresent()) {
            throw new RuntimeException("学生不存在");
        }

        Optional<Course> courseOpt = courseService.findById(courseId);
        if (!courseOpt.isPresent()) {
            throw new RuntimeException("课程不存在");
        }

        Student student = studentOpt.get();
        Course course = courseOpt.get();

        // 检查是否已经预约过该课程
        if (bookingRepository.existsByStudentAndCourse(student, course)) {
            throw new RuntimeException("您已经预约过该课程");
        }

        // 检查课程状态
        if (course.getStatus() == Course.CourseStatus.CLOSED) {
            throw new RuntimeException("课程已关闭，无法预约");
        }

        if (course.getStatus() == Course.CourseStatus.FULL) {
            throw new RuntimeException("课程已满，无法预约");
        }

        // 检查课程是否已满
        long confirmedBookings = bookingRepository.countConfirmedBookingsByCourse(course);
        if (confirmedBookings >= course.getMaxStudents()) {
            // 更新课程状态为已满
            courseService.updateCourseStatus(courseId, Course.CourseStatus.FULL);
            throw new RuntimeException("课程已满，无法预约");
        }
        // 查询是否有预约取消的
        Booking oldBooking = bookingRepository.selectByStudentAndCourse(student.getId(), course.getId());
        if (oldBooking != null && oldBooking.getStatus() == Booking.BookingStatus.CANCELLED) {
            oldBooking.setStatus(Booking.BookingStatus.PENDING);
            oldBooking.setBookingTime(LocalDateTime.now());
            bookingRepository.updateById(oldBooking);
            return oldBooking;
        }
        Booking booking = new Booking();
        booking.setStudentId(studentId);
        booking.setCourseId(courseId);
        booking.setBookingTime(LocalDateTime.now());
        booking.setStatus(Booking.BookingStatus.PENDING);
        bookingRepository.insert(booking);
        return booking;
    }

    public Optional<Booking> findById(Long id) {
        Booking booking = bookingRepository.selectById(id);
        if (booking != null) {
            if (booking.getStudentId() != null){
                Optional<Student> byId = studentService.findById(booking.getStudentId());
                byId.ifPresent(booking::setStudent);
            }
            if (booking.getCourseId() != null) {
                Optional<Course> byId = courseService.findById(booking.getCourseId());
                byId.ifPresent(booking::setCourse);
            }
        }
        return Optional.ofNullable(booking);
    }

    public Optional<Booking> findByStudentAndCourse(Student student, Course course) {
        return bookingRepository.findByStudentAndCourse(student, course);
    }

    public List<Booking> findByStudent(Student student) {
        List<Booking> byStudent = bookingRepository.findByStudent(student);
        for (Booking booking : byStudent) {
            if (booking.getStudentId() != null) {
                Optional<Student> byId = studentService.findById(booking.getStudentId());
                byId.ifPresent(booking::setStudent); // 安全设置 Student
            }
            if (booking.getCourseId() != null) {
                Optional<Course> byId = courseService.findById(booking.getCourseId());
                byId.ifPresent(booking::setCourse);
            }
        }
        return byStudent;
    }

    public List<Booking> findByCourse(Course course) {
        List<Booking> byCourse = bookingRepository.findByCourse(course);
        for (Booking booking : byCourse) {
            if (booking.getStudentId() != null) {
                Optional<Student> byId = studentService.findById(booking.getStudentId());
                byId.ifPresent(booking::setStudent); // 安全设置 Student
            }
            if (booking.getCourseId() != null) {
                Optional<Course> byId = courseService.findById(booking.getCourseId());
                byId.ifPresent(booking::setCourse);
            }
        }
        return byCourse;
    }

    public List<Booking> findByStatus(Booking.BookingStatus status) {
        return bookingRepository.findByStatus(status);
    }

    public List<Booking> findAll() {
        List<Booking> bookingList = bookingRepository.selectList(null);
        for (Booking booking : bookingList) {
            if (booking.getStudentId() != null) {
                Optional<Student> byId = studentService.findById(booking.getStudentId());
                byId.ifPresent(booking::setStudent);
            }
            if (booking.getCourseId() != null) {
                Optional<Course> byId = courseService.findById(booking.getCourseId());
                byId.ifPresent(booking::setCourse);
            }
        }
        return bookingList;
    }

    public Booking updateBookingStatus(Long bookingId, Booking.BookingStatus status) {
        Booking booking = bookingRepository.selectById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预约不存在");
        }

        booking.setStatus(status);
        bookingRepository.updateById(booking);
        return booking;
    }

    public void cancelBooking(Long bookingId) {
        Booking booking = bookingRepository.selectById(bookingId);
        if (booking == null) {
            throw new RuntimeException("预约不存在");
        }

        booking.setStatus(Booking.BookingStatus.CANCELLED);
        bookingRepository.updateById(booking);

        // 检查课程是否需要从FULL状态改为OPEN
        Long courseId = booking.getCourseId();
        Course course = courseService.findById(courseId)
                .orElseThrow(() -> new RuntimeException("课程不存在"));
        if (course.getStatus() == Course.CourseStatus.FULL) {
            long confirmedBookings = bookingRepository.countConfirmedBookingsByCourse(course);
            if (confirmedBookings < course.getMaxStudents()) {
                courseService.updateCourseStatus(course.getId(), Course.CourseStatus.OPEN);
            }
        }
    }

    public void deleteBooking(Long id) {
        if (bookingRepository.selectById(id) == null) {
            throw new RuntimeException("预约不存在");
        }
        bookingRepository.deleteById(id);
    }

    public long getConfirmedBookingsCount(Course course) {
        return bookingRepository.countConfirmedBookingsByCourse(course);
    }

    public boolean existsByStudentAndCourse(Student student, Course course) {
        return bookingRepository.existsByStudentAndCourse(student, course);
    }
}